package za.org.jcicada.datastore.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import za.org.jcicada.datastore.IDataStoreClient;
import za.org.jcicada.genss.messages.Result;
import za.org.jcicada.genss.sensor.ISensorValue;
import za.org.jcicada.genss.sensor.SensorURN;
import za.org.jcicada.genss.sensor.impl.SensorStatusValue;

public class MemoryDataStoreServer extends DataStoreServerAbstract {

	Map<SensorURN, List<ISensorValue>> store = new HashMap<SensorURN, List<ISensorValue>>();
	Map<SensorURN, List<SensorStatusValue>> statusStore = new HashMap<SensorURN, List<SensorStatusValue>>();
	
	@Override
	public void storeSensor(SensorURN sensorURN, ISensorValue value) {
		genericStore(sensorURN, value, store);
	}
	
	@Override
	public void storeSensorStatus(SensorURN sensorURN, SensorStatusValue statusValue) {
		genericStore(sensorURN, statusValue, statusStore);
	}
	
	private <T> void genericStore(SensorURN sensorURN, T value, Map<SensorURN, List<T>> store) {
		if (!store.containsKey(sensorURN)) {
			store.put(sensorURN, new ArrayList<T>());
		}
		store.get(sensorURN).add(value);
	}

	public void retrieveSensorHistory(IDataStoreClient client, SensorURN sensorURN, Date from, Date to) {
		List<ISensorValue> values = new ArrayList<ISensorValue>();
		List<ISensorValue> storedValues = store.get(sensorURN);
		if (storedValues != null) {
			Iterator<ISensorValue> it = storedValues.iterator();
			ISensorValue value = null;
			ISensorValue previousValue = null;
			// search for first valid value
			while (it.hasNext()) {
				value = it.next();
				if (value.getTime() >= from.getTime()) {
					break;
				}
				previousValue = value;
			}
			// add last invalid value (end of previous history)
			if (previousValue != null) {
				values.add(previousValue);
			}
			if (value != null) {
				values.add(value);
			}
			// add valid values
			while (it.hasNext()) {
				value = it.next();
				if (value.getTime() > to.getTime()) {
					break;
				}
				values.add(value);
			}
		}
		client.replySensorHistory(new Result(), sensorURN, from, to, values);
	}
	
	//:TODO use generics to collapse this and previous method, require base interface with getTime()
	public void retrieveStatusHistory(IDataStoreClient client, SensorURN sensorURN, Date from, Date to) {
		List<SensorStatusValue> values = new ArrayList<SensorStatusValue>();
		List<SensorStatusValue> storedValues = statusStore.get(sensorURN);
		if (storedValues != null) {
			Iterator<SensorStatusValue> it = storedValues.iterator();
			SensorStatusValue value = null;
			SensorStatusValue previousValue = null;
			// search for first valid value
			while (it.hasNext()) {
				value = it.next();
				if (value.getTime() >= from.getTime()) {
					break;
				}
				previousValue = value;
			}
			// add last invalid value (end of previous history)
			if (previousValue != null) {
				values.add(previousValue);
			}
			if (value != null) {
				values.add(value);
			}
			// add valid values
			while (it.hasNext()) {
				value = it.next();
				if (value.getTime() > to.getTime()) {
					break;
				}
				values.add(value);
			}
		}
		client.replyStatusHistory(new Result(), sensorURN, from, to, values);
	}
	
}
